#ifndef K_TASK_QUEUE_H
#define K_TASK_QUEUE_H
#pragma once

#include "KAutoPtr.h"
#include "KTaskList.h"
#include <deque>
#include <utility>

class KTaskThread;

class KTask {
public:
    typedef KTaskList::TaskType TaskType;
public:
    KTask() : m_priority(0) {}
    KTask(KTask &&task) : m_priority(task.m_priority), m_task(std::move(task.m_task)) {}
    KTask(TaskType &&task, int priority = 0) : m_priority(priority), m_task(std::move(task)) {}
    KTask(const TaskType &task, int priority = 0) : m_priority(priority), m_task(task) {}
public:
    bool operator<(const KTask &task) const;
    KTask &operator=(KTask &&task);
public:
    void exec() const;
    bool isValid() const;
private:
    int         m_priority;
    TaskType    m_task;
};

class KTaskQueue : KLockable {
public:
    KTaskQueue();
    virtual ~KTaskQueue();
public:
    virtual void start();
    virtual void stop();
    bool submit(KTask &&task);
private:
    void _worker();
    void doTasks();
private:
    volatile bool           m_stopped;
    KAutoEvent              m_newTask;
    KAutoPtr<KTaskThread>   m_worker;
    std::deque<KTask>       m_tasks;
};

inline bool KTask::operator<(const KTask &task) const
{
    return m_priority < task.m_priority;
}

inline KTask &KTask::operator=(KTask &&task)
{
    m_priority = task.m_priority;
    m_task = std::move(task.m_task);
    return *this;
}

inline void KTask::exec() const
{
    if (isValid()) {
        m_task();
    }
}

inline bool KTask::isValid() const
{
    return m_task;
}

#endif // K_TASK_QUEUE_H